//! \file PathSearch.h
//! \brief Defines the <code>fullsail_ai::algorithms::PathSearch</code> class interface.
//! \author Cromwell D. Enage, 2009; Jeremiah Blanchard, 2012
#ifndef _FULLSAIL_AI_PATH_PLANNER_PATH_SEARCH_H_
#define _FULLSAIL_AI_PATH_PLANNER_PATH_SEARCH_H_

#include "../TileSystem/Tile.h"
#include "../TileSystem/TileMap.h"
#include "../platform.h"
#include <vector>
#include <map>
#include "../PriorityQueue.h"

#define BLUE 0xFF0000FF
#define GREEN 0xFF00FF00
#define RED 0xFFFF0000
#define YELLOW 0xFFFFFF00
#define CYAN 0xFF00FFFF
#define MAGENTA 0xFFFF00FF
#define BLACK 0x00000000
#define WHITE 0xFFFFFFFF

#define HEURISTIC_WEIGHT 1.1

namespace fullsail_ai { namespace algorithms {

	struct PlannerNode
	{
		PlannerNode* parent;
		Tile* tile;
		double givenCost;
		double finalCost;
		double heuristicCost;

		PlannerNode(Tile* _tile, double _given, double _heuristic) : parent(0), heuristicCost(_heuristic), finalCost(_heuristic), givenCost(_given), tile(_tile){}
	};

	class PathSearch
	{
	private:
		TileMap* tileMap;
		std::map<Tile*, PlannerNode*> created;
		std::vector<Tile const*> solution;
		PriorityQueue<PlannerNode*> open;
		Tile* goal;

		bool goalFound;

		void DrawPath(PlannerNode* const path);
		void DrawCreated();
		double DistanceBetweenTiles(Tile const* a, Tile const* b);

		void EvaluateTile(int row, int col, PlannerNode* cur);

		void ClearCreated();

	public:
		//! \brief Default constructor.
		DLLEXPORT PathSearch();

		//! \brief Destructor.
		DLLEXPORT ~PathSearch();

		//! \brief Sets the tile map.
		//!
		//! Invoked when the user opens a tile map file.
		//!
		//! \param   _tileMap  the data structure that this algorithm will use
		//!                    to access each tile's location and weight data.
		DLLEXPORT void initialize(TileMap* _tileMap);

		//! \brief Enters and performs the first part of the algorithm.
		//!
		//! Invoked when the user presses one of the play buttons.
		//!
		//! \param   startRow         the row where the start tile is located.
		//! \param   startColumn      the column where the start tile is located.
		//! \param   goalRow          the row where the goal tile is located.
		//! \param   goalColumn       the column where the goal tile is located.
		DLLEXPORT void enter(int _startRow, int _startColumn, int _goalRow, int _goalColumn);

		//! \brief Returns <code>true</code> if and only if no nodes are left open.
		//!
		//! \return  <code>true</code> if no nodes are left open, <code>false</code> otherwise.
		DLLEXPORT bool isDone() const;

		//! \brief Performs the main part of the algorithm until the specified time has elapsed or
		//! no nodes are left open.
		DLLEXPORT void update(long timeslice);

		//! \brief Returns an unmodifiable view of the solution path found by this algorithm.
		DLLEXPORT std::vector<Tile const*> const getSolution() const;

		//! \brief Resets the algorithm.
		DLLEXPORT void exit();

		//! \brief Uninitializes the algorithm before the tile map is unloaded.
		DLLEXPORT void shutdown();
	};

	//bool CheckDistance(PlannerNode* const& a, PlannerNode* const& b);
	static bool CheckDistance(PlannerNode* const& a, PlannerNode* const& b)
	{
		return a->finalCost > b->finalCost;
	}
}}  // namespace fullsail_ai::algorithms

#endif  // _FULLSAIL_AI_PATH_PLANNER_PATH_SEARCH_H_

